require'zdc.deflate'
require'zdc.typeex'
require'zdc.idutil'
module(..., package.seeall)

function GetNodeFromModule(dpl,id,path)
	path=path or ''
	local node_module_name = string.gsub(path.."."..id,"/", ".")
	local ok, node_module = pcall(require, node_module_name)
	if ok then
		local data = node_module.NODE_DATA or zdc.deflate.deflate_node(node_module.NODE)
		local node,errmsg = dpl:_make_node(id,data,0,0,true)
		assert(node,errmsg)
		if node_module.CREATE_DEFAULT then
			dpl:_save_node(node)
			node = dpl:_sure_node(id)
		end
		return node
	else
		return nil
	end
end
function GetNodeFromModuleEx(dpl,id,path,pre)
	local node_module_name
	path=path or ''
	if zdc.idutil.IsRoot(pre,id) then
		local mid=id:sub(#pre+2)
		if #mid==0 then
			node_module_name=string.gsub(path,"/", ".")
		else
			node_module_name=string.gsub(path.."."..mid,"/", ".")
		end
	else
		return nil
	end
	local ok, node_module = pcall(require, node_module_name)
	if ok then
		local data = node_module.NODE_DATA or zdc.deflate.deflate_node(node_module.NODE)
		local node,errmsg = dpl:_make_node(id,data,0,0,true)
		assert(node,errmsg)
		if node_module.CREATE_DEFAULT then
			dpl:_save_node(node)
			node = dpl:_sure_node(id)
		end
		return node
	else
		if not string.match(node_module or '','not found:') then
			print('ERROR load',id,node_module)
		end
		return nil
	end
end

function InitDalFromModules(dal,moddir,modroot,modpre,filter_id_dpl,force)
	local db=require'zdc.ds.moddb'.new{moddir,modroot,modpre}
	local ids=db:get_ids_by_prefix()
	local cnt=0
	for _,v in ipairs(ids) do
		local dpl=dal:GetDpl(v)
		if dpl and (not filter_id_dpl or filter_id_dpl(v,dpl)) then
			if force or not dpl:_has_node(v) then
				print("module",v,"to dpl",dpl)
				dpl:_save_data(v,assert(db:get_node(v)))
				print("Success")
				cnt=cnt+1
			end
		end
	end
	return cnt
end
function InitDalFromX(dal,dbcfg,filter_id_dpl,force)
	local db_module,db_params=dbcfg.MODULE,dbcfg.PARAMS
	local db
	assert(db_module,'bad db_module: '..tostring(db_module))
	if type(db_module)=='table' then
		db = db_module
	else
		local dbm = require(db_module)
		db = dbm.new(db_params)
	end
	local ids=db:get_ids_by_prefix()
	local cnt=0
	for _,v in ipairs(ids) do
		local dpl=dal:GetDpl(v)
		if dpl and (not filter_id_dpl or filter_id_dpl(v,dpl)) then
			if force or not dpl:_has_node(v) then
				dpl:_save_data(v,assert(db:get_node(v)))
				print("Success")
				cnt=cnt+1
			end
		end
	end
	return cnt
end
function ScanDoFromX(dbcfg,scan_do)
	if not scan_do then return 0 end
	
	local db_module,db_params=dbcfg.MODULE,dbcfg.PARAMS
	local db
	assert(db_module,'bad db_module: '..tostring(db_module))
	if type(db_module)=='table' then
		db = db_module
	else
		local dbm = require(db_module)
		db = dbm.new(db_params)
	end
	local ids=db:get_ids_by_prefix()
	local cnt=0
	for _,v in ipairs(ids) do
		if scan_do(db,v) then 
			break
		end
	end
	return cnt
end
function CloneToQuick(dal,fromid,toid,includeroot,needadj,nocommit)
	local pr1,pr2=#fromid+1,#toid+1
	local fdpl=dal:GetDpl(fromid)
	local db=fdpl and fdpl._db
	if not db then return nil,'no dpl for '..fromid end
	local stclk=os.clock()
	--print('Clone','1',os.clock())
	local orgns=db:get_nodes_by_prefix(fromid..'/')
	if includeroot then
		orgns[fromid]=db:get_node(fromid)
	end
	local cnt=0
	--print('Clone','2',os.clock())
	for v,dbn in pairs(orgns) do
		local nv=v:sub(pr1)
		if #nv==0 then nv=toid else nv=toid..nv end
		local dpl=dal:GetDpl(nv)
		if dpl then
			--print("clone",v,"to dpl",dpl, 'toid',nv)
			local nn
			nn=dpl:_make_node(nv,dbn.data,dbn.ik,dbn.ts,true)
			if needadj then
				zdc.typeex.AdjustRefid(nn,fromid,toid)
			end
			nn:__save_ta()
			--print("Success")
			cnt=cnt+1
		end
	end
	--print('Clone','3',os.clock())
	if not nocommit then
		dal:CommitTA()
	end
	--print('Clone','4',os.clock(),os.clock()-stclk)
	return cnt
end
function CloneTo(dal,fromid,toid,includeroot,filter_id_dpl,force,inspto,nocommit)
	local pr1,pr2=#fromid+1,#toid+1
	local fdpl=dal:GetDpl(fromid)
	local db=fdpl and fdpl._db
	if not db then return nil,'no dpl for '..fromid end
	--print('Clone','1',os.clock())
	local ids=db:get_ids_by_prefix(fromid..'/')
	if includeroot then table.insert(ids,fromid) end
	local cnt=0
	--print('Clone','2',os.clock())
	for _,v in ipairs(ids) do
		local nv=v:sub(pr1)
		if #nv==0 then nv=toid else nv=toid..nv end
		local dpl=dal:GetDpl(nv)
		if dpl and (not filter_id_dpl or filter_id_dpl(nv,dpl)) then
			if force or not dpl:_has_node(nv) then
				--print("clone",v,"to dpl",dpl, 'toid',nv)
				local nn
				if inspto then
					nn=dpl:_make_node(nv,"_pto='"..v.."';_ins=true",nil,nil,true)
				else
					local dbn=assert(db:get_node(v))
					nn=dpl:_make_node(nv,dbn.data,dbn.ik,dbn.ts,true)
				end
				zdc.typeex.AdjustRefid(nn,fromid,toid)
				nn:__save_ta()
				--print("Success")
				cnt=cnt+1
			end
		end
	end
	--print('Clone','3',os.clock())
	if not nocommit then
		dal:CommitTA()
	end
	--print('Clone','4',os.clock())
	return cnt
end


